﻿//
// (C) Copyright 2009 Irantha Suwandarathna (iranthas@hotmail.com)
// All rights reserved.
//

#if SILVERLIGHT

using System;
using System.IO;
using System.IO.IsolatedStorage;


namespace EffiProz.Core.Lib
{
    public class FileUtilSlis : EfzFileAccess
    {
        private static FileUtil fileUtil = new FileUtil();


        /** Creates a new instance of FileUtil */
        public FileUtilSlis() { }

        public static FileUtil GetDefaultInstance()
        {
            return fileUtil;
        }

        public override  bool IsStreamElement(string elementName)
        {
            IsolatedStorageFile isoFile =
           IsolatedStorageFile.GetUserStoreForApplication();

            return isoFile.FileExists(elementName);
        }

        override public Stream OpenInputStreamElement(string streamName)
        {
            IsolatedStorageFile isoFile =
           IsolatedStorageFile.GetUserStoreForApplication();

            try
            {
                IsolatedStorageFileStream isoStream =  new IsolatedStorageFileStream(streamName,
                        FileMode.Open,  FileAccess.Read, isoFile);

                return isoStream;
            }
            catch (Exception e)
            {
                throw toIOException(e);
            }
        }

        override public void CreateParentDirs(String filename)
        {
            IsolatedStorageFile isoFile =
           IsolatedStorageFile.GetUserStoreForApplication();

            int sep = filename.LastIndexOf(Path.DirectorySeparatorChar);
            if (sep == -1)
                sep = filename.LastIndexOf(Path.AltDirectorySeparatorChar);

            if (sep == -1)
                return;

            string dirPath = filename.Substring(0, filename.Length - sep);
            if (!isoFile.DirectoryExists(dirPath))
                isoFile.CreateDirectory(dirPath);
           
        }

        public override String makeDirectories(String path)
        {
            IsolatedStorageFile isoFile =
           IsolatedStorageFile.GetUserStoreForApplication();

            try
            {
                isoFile.CreateDirectory(path);

                return path;
            }
            catch (IOException)
            {
                return null;
            }
        }

      

        override public void RenameElement(String oldName, String newName)
        {
            renameOverwrite(oldName, newName);
        }

        override public Stream OpenOutputStreamElement(String streamName)
        {
            IsolatedStorageFile isoFile =
            IsolatedStorageFile.GetUserStoreForApplication();
            

             IsolatedStorageFileStream isoStream =  new IsolatedStorageFileStream(streamName,
                        FileMode.Create ,  FileAccess.ReadWrite, isoFile);

             return isoStream;
        }

        override public FileStream OpenOutputStreamElement(string streamName, FileMode mode,
            FileAccess access)
        {
            IsolatedStorageFile isoFile =
           IsolatedStorageFile.GetUserStoreForApplication();


            IsolatedStorageFileStream isoStream = new IsolatedStorageFileStream(streamName,
                       mode, access, isoFile);

            return isoStream;
        }

        public override void removeElement(String filename)
        {
            delete(filename);   
        }

          
        /**
         * Delete the named file
         */
        private void delete(string filename)
        {
            IsolatedStorageFile isoFile =
           IsolatedStorageFile.GetUserStoreForApplication();

            if (isoFile.FileExists(filename))
                isoFile.DeleteFile(filename);  
        }

        /**
         * Requests, _in a JDK 1.1 compliant way, that the file or directory denoted
         * by the given abstract pathname be deleted when the virtual machine
         * terminates. <p>
         *
         * Deletion will be attempted only for JDK 1.2 and greater runtime
         * environments and only upon normal termination of the virtual
         * machine, as defined by the Java Language Specification. <p>
         *
         * Once deletion has been sucessfully requested, it is not possible to
         * cancel the request. This method should therefore be used with care. <p>
         *
         * @param f the abstract pathname of the file be deleted when the virtual
         *       machine terminates
         */
        public override void deleteOnExit(string file)
        {
            //JavaSystem.deleteOnExit(f); TODO
        }

        /**
         * Return true or false based on whether the named file exists.
         */
        public override bool exists(string filename)
        {
            IsolatedStorageFile isoFile =
           IsolatedStorageFile.GetUserStoreForApplication();
            return isoFile.FileExists(filename);
        }

        public override string getParentDir(string filename)
        {
            IsolatedStorageFile isoFile =
           IsolatedStorageFile.GetUserStoreForApplication();

            int sep = filename.LastIndexOf(Path.DirectorySeparatorChar);
            if (sep == -1)
                sep = filename.LastIndexOf(Path.AltDirectorySeparatorChar);

            if (sep == -1)
                return ".";

            string parent = filename.Substring(0, filename.Length - sep);

            return parent;
        }

        public override string[] getAllFiles(string dirName)
        {
            IsolatedStorageFile isoFile =
           IsolatedStorageFile.GetUserStoreForApplication();
            return isoFile.GetFileNames(dirName);
        }

      
        /**
         * Rename the file with oldname to newname. If a file with newname already
         * exists, it is deleted before the renaming operation proceeds.
         *
         * If a file with oldname does not exist, no file will exist after the
         * operation.
         */
        private void renameOverwrite(string oldname, string newname)
        {
            IsolatedStorageFile isoFile =
           IsolatedStorageFile.GetUserStoreForApplication();

            delete(newname);
           
            if (exists(oldname))
            {              
                using (var readStream = new IsolatedStorageFileStream(oldname, FileMode.Open,FileAccess.Read, isoFile))
                using (var writeStream = new IsolatedStorageFileStream(newname, FileMode.Create,FileAccess.Write, isoFile))
                using (var reader = new StreamReader(readStream))
                using (var writer = new StreamWriter(writeStream))
                {
                    writer.Write(reader.ReadToEnd());
                    writer.Flush();
                }
            }
        }


        public static IOException toIOException(Exception e)
        {
            if (e is IOException)
            {
                return (IOException)e;
            }
            else
            {
                return new IOException(e.ToString());
            }
        }

        /**
         * Retrieves the absolute path, given some path specification.
         *
         * @param path the path for which to retrieve the absolute path
         * @return the absolute path
         */
        public string absolutePath(string path)
        {
            return path;
        }

      

        /**
         * Retrieves the canonical file for the given path, _in a
         * JDK 1.1 complaint way.
         *
         * @param path the path for which to retrieve the canonical File
         * @return the canonical File
         */
        public string canonicalFile(string path)
        {
            return path;
        }

        /**
         * Retrieves the canonical path for the given path, _in a
         * JDK 1.1 complaint way.
         *
         * @param path the path for which to retrieve the canonical path
         * @return the canonical path
         */
        public override string canonicalPath(string path)
        {
            return path;
        }

        /**
         * Retrieves the canonical path for the given path, or the absolute
         * path if attemting to retrieve the canonical path fails.
         *
         * @param path the path for which to retrieve the canonical or
         *      absolute path
         * @return the canonical or absolute path
         */
        public override string CanonicalOrAbsolutePath(string path)
        {
            return path;           
        }

      
      

        public class FileSync : IFileSync
        {

            FileStream outDescriptor;

            public FileSync(FileStream os)
            {
                outDescriptor = os;
            }

            public void Sync()
            {
                outDescriptor.Flush();
            }
        }

        override public IFileSync GetFileSync(Stream os)
        {
            return new FileSync((FileStream)os);
        }
    }

    
}

#endif
